package impl

import (
	"context"
	"errors"
	"fmt"
	"github.com/sirupsen/logrus"
	"monoblog/common/register"
	"monoblog/config"
	"monoblog/domain/dao"
	"monoblog/domain/dto"
	"monoblog/domain/model"
	"monoblog/domain/service"
	"strings"
)

func init() {
	register.RegisterInstance[service.SearchService]("SearchService", func() service.SearchService {
		return &SearchServiceWithManticore{
			userRepository: dao.NewUserRepository(),
		} // 返回唯一实例
	})
}

type SearchServiceWithManticore struct {
	userRepository *dao.UserRepository
}

func (s *SearchServiceWithManticore) ClearHidden(ctx context.Context) error {
	sql := fmt.Sprintf(`DELETE FROM blog_doc WHERE hidden=1 `)

	r, err := config.GetMsDB().Exec(sql)
	if err != nil {
		logrus.Errorf("[aid: %s] clear hidden blog failed.  err: %v", ctx.Value("aid"), err.Error())
		return err
	}
	n, _ := r.RowsAffected()
	logrus.Infof("[aid: %s] clear hidden blog success.  rows %d", ctx.Value("aid"), n)

	return nil
}

func (s *SearchServiceWithManticore) ExistSearch(ctx context.Context, blogId string) (bool, error) {
	sql := fmt.Sprintf(`SELECT COUNT(*) FROM blog_doc WHERE blog_id = '%s'`, blogId)

	var count int
	err := config.GetMsDB().QueryRow(sql).Scan(&count)
	if err != nil {
		logrus.Errorf("[aid: %s] search exist blog failed. blog_id: %s, err: %v", ctx.Value("aid"), blogId, err.Error())
		return false, err
	}
	return count > 0, nil
}

func (s *SearchServiceWithManticore) PushData(ctx context.Context, blog *model.Article) error {
	if blog.BlogStats == nil {
		logrus.Errorf("[aid: %s] search push blog failed. blog_id: %s, err: %v", ctx.Value("aid"), blog.ID, "obj.BlogStats is nil")
		return errors.New("obj.BlogStats is nil")
	}
	blogDoc := dto.ConvertArticleToBlogDoc(blog, 0)

	var _id int //主键ID
	idSql := fmt.Sprintf(`SELECT id FROM blog_doc WHERE blog_id = '%s'`, blog.ID)
	config.GetMsDB().QueryRow(idSql).Scan(&_id)

	// 插入或更新数据
	sql := fmt.Sprintf(`
		REPLACE INTO blog_doc (
			blog_id, title, category_id, category_name, show_text, photo
			, author_id, author_name, author_avatar,hidden, publish_time
			,  click_count, comment_count, like_count, favorite_count
			, id
		) VALUES (
			'%s', '%s', '%s', '%s', '%s', '%s'
			, '%s', '%s', '%s', %d, %d
			, %d, %d, %d, %d
			, %d
		)`,
		blogDoc.BlogId, blogDoc.Title, blogDoc.CategoryId, blogDoc.CategoryName, blogDoc.ShowText, blogDoc.Photo,
		blogDoc.AuthorId, blogDoc.AuthorName, blogDoc.AuthorAvatar, blogDoc.Hidden, blogDoc.PublishTime,
		blogDoc.ClickCount, blogDoc.CommentCount, blogDoc.LikeCount, blogDoc.FavoriteCount,
		_id,
	)

	logrus.Debugf("[aid: %s] search insert blog sql: \n%s", ctx.Value("aid"), sql)
	_, err := config.GetMsDB().Exec(sql)
	if err != nil {
		logrus.Errorf("[aid: %s] search insert blog failed. blog_id: %s, err: %v", ctx.Value("aid"), blogDoc.BlogId, err.Error())
		return err
	}

	return nil
}

func (s *SearchServiceWithManticore) BatchPushData(ctx context.Context, list []*model.Article) error {
	if len(list) == 0 {
		return nil
	}

	for _, blog := range list {
		err := s.PushData(ctx, blog)
		if err != nil {
			return err
		}
	}
	return nil
}

func (s *SearchServiceWithManticore) DeleteByBlogIds(ctx context.Context, blogIds []string) error {
	if len(blogIds) == 0 {
		return nil
	}
	sql := fmt.Sprintf(`DELETE FROM blog_doc WHERE blog_id IN (%s)`, strings.Join(blogIds, ","))

	res, err := config.GetMsDB().Exec(sql)
	fmt.Println("inserted blog res: ", res)
	return err
}

func (s *SearchServiceWithManticore) UpdateData(ctx context.Context, list []*model.BlogStats) error {
	for _, stats := range list {
		sql := fmt.Sprintf(`update blog_doc set click_count=%d, comment_count=%d, like_count=%d, favorite_count=%d WHERE blog_id='%s'`,
			stats.ClickCount, stats.CommentCount, stats.LikeCount, stats.FavoriteCount, stats.ID)

		_, err := config.GetMsDB().Exec(sql)
		if err != nil {
			logrus.Errorf("[aid: %s] search update blog failed. blog_id: %s, err: %v", ctx.Value("aid"), stats.ID, err.Error())
			return err
		}
	}
	return nil
}

func (s *SearchServiceWithManticore) SearchBlogs(ctx context.Context, query dto.SearchQuery) ([]*model.BlogDoc, error) {
	var blogs = make([]*model.BlogDoc, 0)

	sql := fmt.Sprintf(`select  highlight({},'title') as light_title,highlight({},'show_text') as light_text, * 
			from blog_doc where match('%s') and hidden=0 `, query.Kw)

	err := config.GetMsDB().Select(&blogs, sql)
	if err != nil {
		logrus.Errorf("[aid: %s] search blogs failed. query: %s, err: %v", ctx.Value("aid"), query, err.Error())
	}
	return blogs, err
}

func (s *SearchServiceWithManticore) SearchAuthors(ctx context.Context, query dto.SearchQuery) ([]*model.WebUser, error) {
	userQuery := dto.UserQuery{
		BaseQuery: query.BaseQuery,
		Nickname:  query.Kw,
	}

	users, _, err := s.userRepository.FindList(userQuery)
	if err != nil {
		logrus.Errorf("[aid: %s] search authors failed. query: %s, err: %v", ctx.Value("aid"), query, err.Error())
		return nil, err
	}
	return users, nil
}
